package com.atguigu.lease.web.api.interceptor;

import com.atguigu.lease.common.exception.StgyException;
import com.atguigu.lease.common.result.ResultCodeEnum;
import com.atguigu.lease.common.util.JwtUtil;
import com.atguigu.lease.model.entity.UserInfo;
import com.atguigu.lease.web.api.vo.UserInfoVo;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import java.util.Map;
@Component
public class StgyApiAuthInpterceptor implements HandlerInterceptor {
    /*
        filter:  对访问servlet的请求进行拦截过滤
            服务器的组件之一 ，装配使用springioc容器中的组件对象 不方便

        springmvc interceptor： 对 controller接口访问前后进行拦截
                对访问接口的方法进行拦截 进行登录校验
                在业务方法中可能需要使用token中的数据 或者基于token解析得到的用户信息(id)
                - 可以方便使用容器中的其他对象  或者 透传数据(拦截器将解析的结果 传递给 接口方法)
                - 拦截器可以基于路径表达式 进行判断  是否要拦截一个请求
                使用场景： 需要通过路径匹配拦截处理、透传数据
        aop： 对 方法进行增强    事务管理 前后日志输出  异常捕获  缓存管理
            判断用户是否登录： 获取token  解析token（得到claims）....
            通过反射调用目标方法:  aop不便于将解析token的结果传入
                使用场景： 不需要透传数据、被增强的方法没有统一的特点
     */
    public static final ThreadLocal<UserInfo> THREAD_LOCAL = new ThreadLocal<>();
    //接口方法执行前调用
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //访问目标接口的方法，可以获取请求头中的token 解析判断用户登录状态是否有效
        String accessToken = request.getHeader("access_token");
        if(StringUtils.isEmpty(accessToken)){
            throw new StgyException(ResultCodeEnum.APP_LOGIN_AUTH);
        }
        Map<String, Object> map = JwtUtil.parseToken(accessToken, request);
        //将Map的数据转为UserInfo对象
        String avatar = map.get("avatar").toString();
        String userName = map.get("userName").toString();
        Long userId = Long.parseLong(map.get("userId").toString());
        UserInfo userInfo = new UserInfo();
        userInfo.setNickname(userName);
        userInfo.setId(userId);
        userInfo.setAvatarUrl(avatar);
        //共享数据
        THREAD_LOCAL.set(userInfo);
//        如果失效 拒绝访问
        //如果有效 放行请求  同时将token解析的结果缓存透传给后续的业务
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        THREAD_LOCAL.remove();
    }
}
